package com.frame.project.service.system.dict.imp;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.persistence.criteria.Predicate;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.frame.common.constant.UserConstants;
import com.frame.common.enumutil.RemoveEnum;
import com.frame.common.utils.StringUtils;
import com.frame.common.utils.text.Convert;
import com.frame.framework.utils.dict.DictUtils;
import com.frame.framework.web.domain.Ztree;
import com.frame.framework.web.error.WebError;
import com.frame.framework.web.service.imp.AbstractBaseService;
import com.frame.project.domain.system.dict.DictData;
import com.frame.project.domain.system.dict.DictType;
import com.frame.project.repository.system.dict.DictDataRepository;
import com.frame.project.repository.system.dict.DictTypeRepository;
import com.frame.project.service.system.dict.IDictTypeService;

/**
 * 
 * @className ：DictTypeServiceImpl
 * @describe ：字典类型
 */
@Service
public class IDictTypeServiceImpl extends AbstractBaseService<DictType> implements IDictTypeService {

	@Autowired
	private DictDataRepository dictDataRepository;
	
	@Autowired
	private DictTypeRepository dictTypeRepository;
	
	/**
     * 项目启动时，初始化字典到缓存
     */
    @PostConstruct
    public void init()
    {
    	loadingDictCache();
    }
    
    /**
	 * 分页
	*/
	@Override
	public Page<DictType> findByPage(Integer pageNo, Integer pageSize, DictType dictType) {
		List<Sort.Order> orders = new ArrayList<>();
		orders.add(new Sort.Order(Sort.Direction.ASC, "id"));
		Sort sort = Sort.by(orders);
		Pageable pageable = PageRequest.of(pageNo, pageSize, sort);
		
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		
		Page<DictType> page = dictTypeRepository.findAll((root, query, cb) ->{
			List<Predicate> list = new ArrayList<>();
			list.add(cb.and(cb.equal(root.get("removeStatus").as(Integer.class), RemoveEnum.NOT_REMOVE.getCode())));
			
			if(StringUtils.isNotBlank(dictType.getDictName())) {
				list.add(cb.and(cb.like(root.get("dictName").as(String.class), dictType.getDictName())));
			}
			
			if(StringUtils.isNotBlank(dictType.getStatus())) {
				list.add(cb.and(cb.equal(root.get("status").as(String.class), dictType.getStatus())));
			}
			
			if(StringUtils.isNotBlank(dictType.getDictTypes())) {
				list.add(cb.and(cb.like(root.get("dictTypes").as(String.class), dictType.getDictTypes())));
			}
			
			Map<String, Object> params = dictType.getParams();
			if(!params.isEmpty()) {
				String beginTime = (String) params.get("beginTime");
				String endTime = (String) params.get("endTime");
				if(StringUtils.isNotBlank(beginTime)) {
					try {
						list.add(cb.and(cb.greaterThanOrEqualTo(root.get("createTime"), sdf.parse(beginTime))));
					} catch (ParseException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				if(StringUtils.isNotBlank(endTime)) {
					try {
						list.add(cb.and(cb.lessThanOrEqualTo(root.get("createTime"), sdf.parse(endTime))));
					} catch (ParseException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
			
			Predicate[] p = new Predicate[list.size()];
			return cb.and(list.toArray(p));
		},pageable);
		
		return page;
	}
	
	 /**
     * 根据所有字典类型
     * 
     * @return 字典类型集合信息
     */
    @Override
    public List<DictType> selectDictTypeAll()
    {
        return findAllByRs(RemoveEnum.NOT_REMOVE.getCode());
    }
    
    /**
     * 根据字典类型查询信息
     * 
     * @param dictType 字典类型
     * @return 字典类型
     */
    @Override
    public DictType selectDictTypeByType(String dictType)
    {
        return dictTypeRepository.findByDictTypes(dictType);
    }
    
    /**
     * 新增保存字典类型信息
     * 
     * @param dictType 字典类型信息
     * @return 结果
     */
    @Override
    public void insertDictType(DictType dictType)
    {
    	add(dictType);
    	DictUtils.setDictCache(dictType.getDictTypes(), null);
    }
    
    /**
     * 修改保存字典类型信息
     * 
     * @param dictType 字典类型信息
     * @return 结果
     */
    @Override
    @Transactional
    public void updateDictType(DictType dictType)
    {
        DictType oldType = findById(dictType.getId());
        List<DictData> oldData = dictDataRepository.findByDictType(oldType.getDictTypes());
        if(oldData.size() > 0) {
        	dictDataRepository.updateDictDataType(dictType.getDictTypes(), oldType.getDictTypes());
        }
        oldType.setDictName(dictType.getDictName());
        oldType.setDictTypes(dictType.getDictTypes());
        oldType.setStatus(dictType.getStatus());
        oldType.setRemark(dictType.getRemark());
        modify(oldType);

        List<DictData> dictDatas = dictDataRepository.findDictDataByType(dictType.getDictTypes());
        DictUtils.setDictCache(dictType.getDictTypes(), dictDatas);
    }
    
    /**
     * 批量删除字典类型
     * 
     * @param ids 需要删除的数据
     * @return 结果
     */
    @Override
    public WebError deleteDictTypeByIds(String ids)
    {
        Long[] dictIds = Convert.toLongArray(ids);
        for (Long dictId : dictIds)
        {
            DictType dictType = findById(dictId);
            if (dictDataRepository.countDictDataByType(dictType.getDictTypes()) > 0)
            {
                return new WebError(-1, dictType.getDictName() + "已分配,不能删除");
            }
        }
        
        for(Long id : dictIds) {
        	DictType dict = findById(id);
        	delete(id);
        	DictUtils.removeDictCache(dict.getDictTypes());
        }
        
        
        return new WebError();
    }
    
    /**
     * 校验字典类型称是否唯一
     * 
     * @param dict 字典类型
     * @return 结果
     */
    @Override
    public String checkDictTypeUnique(DictType dict)
    {
        Long dictId = StringUtils.isNull(dict.getId()) ? -1L : dict.getId();
        DictType dictType = dictTypeRepository.findByDictTypes(dict.getDictTypes());
        
        if (StringUtils.isNotNull(dictType) && dictType.getId() != dictId)
        {
            return UserConstants.POST_CODE_NOT_UNIQUE;
        }
        return UserConstants.POST_CODE_UNIQUE;
    }
    
    /**
     * 查询字典类型树
     * 
     * @param dictType 字典类型
     * @return 所有字典类型
     */
    @Override
    public List<Ztree> selectDictTree(DictType dictType)
    {
        List<Ztree> ztrees = new ArrayList<Ztree>();
        Page<DictType> page = findByPage(0, Integer.MAX_VALUE, dictType);
        List<DictType> dictList = page.getContent();
        for (DictType dict : dictList)
        {
            if (UserConstants.DICT_NORMAL.equals(dict.getStatus()))
            {
                Ztree ztree = new Ztree();
                ztree.setId(dict.getId());
                ztree.setName(transDictName(dict));
                ztree.setTitle(dict.getDictTypes());
                ztrees.add(ztree);
            }
        }
        return ztrees;
    }

    /**
     * 加载字典缓存数据
     */
    @Override
    public void loadingDictCache()
    {
        List<DictType> dictTypeList = findAllByRs(RemoveEnum.NOT_REMOVE.getCode());
        for (DictType dict : dictTypeList)
        {
            List<DictData> dictDatas = dictDataRepository.findByDictType(dict.getDictTypes());
            DictUtils.setDictCache(dict.getDictTypes(), dictDatas);
        }
    }

    /**
     * 清空字典缓存数据
     */
    @Override
    public void clearDictCache()
    {
        DictUtils.clearDictCache();
    }

    /**
     * 重置字典缓存数据
     */
    @Override
    public void resetDictCache()
    {
        clearDictCache();
        loadingDictCache();
    }
    
    public String transDictName(DictType dictType)
    {
        StringBuffer sb = new StringBuffer();
        sb.append("(" + dictType.getDictName() + ")");
        sb.append("&nbsp;&nbsp;&nbsp;" + dictType.getDictTypes());
        return sb.toString();
    }
}
